package TCP;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

//基于TCP的服务器
public class EchoServer {
    private ServerSocket serverSocket; //服务器套接字
    
    public EchoServer(int port) throws IOException { //构造方法，用于创建服务器套接字
        serverSocket = new ServerSocket(port); //创建服务器套接字
    }

    //启动服务器
    public void start() throws IOException { 
        System.out.println("服务器已启动，等待客户端连接..."); //打印服务器已启动的信息
        ExecutorService threadPool = Executors.newCachedThreadPool(); //创建线程池

        while(true) { //循环等待客户端连接
            Socket socket = serverSocket.accept(); //等待客户端连接，返回客户端套接字
            threadPool.submit(() -> {
                processConnection(socket);
            });
        }
    }

    //处理客户端连接
    private void processConnection(Socket socket) { 
        //打印客户端已连接的信息
        System.out.printf("[%s:%d] client online!\n", socket.getInetAddress().toString(), socket.getPort()); 

        try(InputStream inputStream = socket.getInputStream();
            OutputStream outputStream = socket.getOutputStream();
            Scanner in = new Scanner(inputStream); 
            PrintWriter out = new PrintWriter(outputStream, true)){
            //获取输入流和输出流，创建输入流扫描器和输出流打印器
            while(true) { //循环接收客户端发送的数据
                if(!in.hasNext()) { //如果没有数据，退出循环
                    System.out.printf("[%s:%d] client offline!\n", socket.getInetAddress().toString(), socket.getPort()); //打印客户端已断开的信息
                    break; //退出循环
                }
                // 1.接收客户端发送的数据
                String request = in.next(); 
                System.out.println("服务器接受到数据："+request);//打印客户端发送的数据
                // 2.处理客户端发送的数据
                String response = process(request);
                // 3.把响应的数据发送给客户端
                out.println(response);
                // 4.刷新输出流，确保数据立即发送给客户端!!!
                out.flush();
                System.out.println("服务器响应数据："+response);//打印服务器响应的数据
                System.out.printf("[%s:%d] req: %s; resp: %s\n", socket.getInetAddress().toString(), socket.getPort(), 
                    request, response);//打印服务器接收到的数据和响应的数据
            }
            } catch (IOException e) {
                e.printStackTrace();
            }finally { //关闭客户端套接字
                try {
                    socket.close(); 
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    }

    //回显处理
    private String process(String request) { //处理客户端发送的数据
        return request; //返回客户端发送的数据
    }

    public static void main(String[] args) throws IOException { //主方法，用于启动服务器
        EchoServer echoServer = new EchoServer(8080); //创建服务器对象
        echoServer.start(); //启动服务器
    }
}
